package com.example.hms.service.servicelmpl;

import com.example.hms.dao.UserDao;
import com.example.hms.entity.SystemLog;
import com.example.hms.entity.User;
import com.example.hms.service.SystemLogService;
import com.example.hms.service.UserService;
import com.example.hms.util.Result;
import com.example.hms.util.ResultSubmit;
import com.example.hms.util.TokenUtil;
import com.example.hms.util.UserResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import javax.net.ssl.HandshakeCompletedEvent;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

//@Service 通常配合 @Transactional 注解使用，用于声明事务边界
@Service
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.READ_COMMITTED,rollbackFor = Exception.class)
public class UserServiceImpl implements UserService {
    @Resource
    UserDao userDao;

    //创建一个日期格式化对象，用于将日期时间按照 yyyy-MM-dd HH:mm:ss 的格式进行解析和格式化。
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

//   Resource 被用来注入 UserDao 和 SystemLogService 实例，使得 UserServiceImpl 类可以直接使用这些服务对象而无需手动创建。
    @Resource
    SystemLogService systemLogService;


    @Override
//    HttpServletRequest 用于封装 HTTP 请求的相关信息
    public Result login(String userId, String userPassWord, HttpServletRequest request) {
        try {
            // 查询用户信息
            User user = userDao.login(userId);
            if (user == null) {
                // 用户不存在的情况
                return ResultSubmit.error("登录失败，用户不存在。");
            } else if (userPassWord.equals(user.getUserPassWord())) {
                // 用户密码正确的处理逻辑  session 存储用户信息
                HttpSession session = request.getSession();
                // 将用户信息保存到会话中
                //setAttribute 是 HttpSession 接口中的方法，用于将对象绑定到会话中，以便在多个请求之间共享数据。
                //存储用户ID，用于标识当前登录的用户身份。
                session.setAttribute("userId", user.getUserId());
                //存储用户密码，用于页面显示或权限判断。
                session.setAttribute("userPassWord", userPassWord);
                //存储角色名，用于做基于角色的权限控制。
                session.setAttribute("userName", user.getUserName());
                //存储角色名称，用于做基于角色的权限控制。
                session.setAttribute("roleName", user.getRoleName());
                // 记录登录时间
                Long time = System.currentTimeMillis();
                session.setAttribute("time", time);

                // 生成并保存token  存储生成的 token，用于后续请求的身份认证。
                session.setAttribute("token", TokenUtil.getToken(
                        String.valueOf(user.getUserId()), user.getUserName(), user.getRoleName(), time));

                // 系统记录
                // 用于封装本次操作的日志信息
                SystemLog systemLog = new SystemLog();
                // 设置操作用户信息 设置执行该操作的用户 ID 和角色名称，用于标识是谁进行了本次操作
                systemLog.setUserId(user.getUserId());
                systemLog.setRoleName(user.getRoleName());
                //设置操作时间  使用之前定义的 SimpleDateFormat 对象将当前时间格式化为 yyyy-MM-dd HH:mm:ss 字符串，表示操作发生的时间。
                systemLog.setCreateTime(format.format(new Date()));
                //设置操作涉及的数据表名 表示本次操作涉及的数据库表名称，这里是 user 表。
                systemLog.setUseTableName("user");
                //设置操作前后数据的主键 ID
                //记录操作前后的数据 ID。由于是登录操作，并没有修改数据，所以操作前后 ID 相同。
                systemLog.setUseTableDataIdBefore(String.valueOf(user.getUserTableId()));
                systemLog.setUseTableDataIdAfter(String.valueOf(user.getUserTableId()));
                //设置操作类 标识本次操作的类型为“用户登录”。
                systemLog.setUseType("用户登录");
                //插入系统日志  调用 SystemLogService 的插入方法，将日志写入数据库。
                systemLogService.insert(systemLog);
                // 返回登录成功结果
                return ResultSubmit.success(sweet(user));
            } else {
                // 用户密码错误的情况
                return ResultSubmit.error("登录失败，密码错误。");
            }
        } catch (Exception e) {
            // 捕获异常并记录日志（如果有日志框架如 logback 或 log4j 可替换为实际日志输出）
            e.printStackTrace();
            // 返回统一的错误信息给前端
            return ResultSubmit.error("登录过程中发生异常：" + e.getMessage());
        }
    }

    private UserResult sweet(User user){
        // 创建一个新的 UserResult 对象
        UserResult userResult = new UserResult();
        // 将 User 对象中的部分属性赋值给 UserResult
        userResult.setUserId(user.getUserId());
        userResult.setUserName(user.getUserName());
        userResult.setRoleName(user.getRoleName());
        // 返回封装后的结果对象
        return userResult;
    }

    @Override
    public Result info(HttpServletRequest request) {
        // 定义session类获取信息
        //getAttribute 是 HttpSession 接口中的方法，用于从会话对象中获取绑定的属性值。
        HttpSession session = request.getSession();
        session.getAttribute("userId");
        session.getAttribute("userName");
        session.getAttribute("roleName");
        // 1. MAP 返回
        // Map是一个接口 放键值
//        Map<String,String> map = new HashMap<>();
//        // toString() 和 (String) 转换数据类型
//        // map.put 将指定的键值对插入到 Map 集合中
//        map.put("userId",session.getAttribute("userId").toString());
//        map.put("userName",(String) session.getAttribute("userName"));
//        map.put("roleName",session.getAttribute("roleName").toString());
//        return ResultSubmit.success(map);

        // 2. 包装类返回
        UserResult userResult = new UserResult();
        //从session中获取userId,通过userId去数据库查询用户信息，更新session中的用户信息
        String userId = session.getAttribute("userId").toString();
        User user = userDao.login(userId);
        userResult.setUserId(user.getUserId());
        userResult.setUserName(user.getUserName());
        userResult.setRoleName(user.getRoleName());


        // Integer 转换数据类型
//        userResult.setUserId((Integer) session.getAttribute("userId"));
//        userResult.setUserName(session.getAttribute("userName").toString());
//        userResult.setRoleName(session.getAttribute("roleName").toString());

        // todo 系统记录
        return ResultSubmit.success(userResult );
    };

    @Override
    public Result selectAllUser(String userId, String userName, String roleName) {
        List<User> users= userDao.selectAllUser(userId,userName,roleName);
        return  ResultSubmit.success(users);
    }

    @Override
    public Result insert(User user, HttpServletRequest request) {
        user.setCreateTime(format.format(new Date()));
        user.setUserId(Math.abs ((int) System.currentTimeMillis()));
        user.setRoleId(2);
        user.setDelete_("未删除");
//        int返回类型代码
        int inserts=userDao.insert(user);

        // 创建系统日志对象，用于记录用户操作
        SystemLog systemLog = new SystemLog();

        // 从会话中获取当前操作用户的ID和角色名称
        systemLog.setUserId((Integer) request.getSession().getAttribute("userId"));
        systemLog.setRoleName((String) request.getSession().getAttribute("roleName"));

        // 设置系统日志创建时间
        systemLog.setCreateTime(format.format(new Date()));

        // 记录操作的表名为"user"
        systemLog.setUseTableName("user");

        // 去除以下注释可以记录操作前的数据ID
        // systemLog.setUseTableDataIdBefore(String.valueOf(user.getUserTableId()));

        // 通过用户ID、用户名和角色名称查询用户，以获取操作后的数据ID
        User user1 = userDao.selectAllUser(String.valueOf(user.getUserId()), user.getUserName(), user.getRoleName()).get(0);

        // 记录操作后的数据ID
        systemLog.setUseTableDataIdAfter(String.valueOf(user1.getUserTableId()));

        // 设置操作类型为“用户新增”
        systemLog.setUseType("用户新增");
        // 调用系统日志服务的插入方法，记录本次操作
        systemLogService.insert(systemLog);


        if(inserts == 0){
            return ResultSubmit.error("添加失败");
        }else{
            // 手动回滚 (事务回滚)
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResultSubmit.success("添加成功");
        }
    }

//    修改
    @Override
    public Result update(User user, HttpServletRequest request) {
        //    逻辑删除原数据
//    修改传入数据中的基础信息，比如：删除标识，创建时间
//    清除userTableId
//    插入新数据
//    todo 系统记录
//    根据删除方法，新增方法返回值判断逻辑修改整个功能是否执行成功
//    不成功则返回报错并回滚
        int updates=userDao.update(user);
        user.setCreateTime(format.format(new Date()));
        user.setDelete_("未删除");
//        user.setUserTableId(0);
        int inserts=userDao.insert(user);

        SystemLog systemLog = new SystemLog();
        systemLog.setUserId((Integer) request.getSession().getAttribute("userId"));
        systemLog.setRoleName((String) request.getSession().getAttribute("roleName"));
        systemLog.setCreateTime(format.format(new Date()));
        systemLog.setUseTableName("user");
        User user1 = userDao.selectAllUser(String.valueOf(user.getUserId()), user.getUserName(), user.getRoleName()).get(0);
        systemLog.setUseTableDataIdAfter(String.valueOf(user1.getUserTableId()));
        systemLog.setUseTableDataIdBefore(String.valueOf(user.getUserTableId()));
        systemLog.setUseType("用户更新");
        systemLogService.insert(systemLog);


        if(inserts == 1 || updates == 1){
            return ResultSubmit.success("修改成功");
        }else{
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResultSubmit.error("修改失败");
        }
    }


//    删除
//    前端传递参数仅为userId
//    根据userId查询用户信息
//    根据用户信息执行逻辑删除
//    todo 系统记录
//    根据删除方法返回值判断整个逻辑删除功能是否执行成功
//    不成功则返回报错并回滚
    @Override
    public Result delete(String userId, HttpServletRequest request){
        User user = userDao.login(userId);
        int updates=userDao.update(user);

        // 创建系统日志对象，用于记录用户操作
        SystemLog systemLog = new SystemLog();
        systemLog.setUserId((Integer) request.getSession().getAttribute("userId"));
        systemLog.setRoleName((String) request.getSession().getAttribute("roleName"));
        systemLog.setCreateTime(format.format(new Date()));
        systemLog.setUseTableName("user");
        systemLog.setUseTableDataIdBefore(String.valueOf(user.getUserTableId()));
        systemLog.setUseType("用户删除");
        systemLogService.insert(systemLog);


        if(updates == 1){
            return ResultSubmit.success("删除成功");
        }else{
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResultSubmit.error("删除失败");
        }
    }
}
